package com.hsh.gaoqianlianmeng.utils;


import com.hsh.gaoqianlianmeng.constants.DateTimeConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.FatalBeanException;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 不同实体类之间的转化
 */
@Slf4j
public class MyBeanUtils extends BeanUtils {
    /**
     * 集合内的数据转为另一个实体类
     *
     * @param sourceList
     * @param tClass
     * @param <S>
     * @param <T>
     * @return
     */
    public static <S, T> List<T> copyList(List<S> sourceList, Class<T> tClass) {
        List<T> targetList = new ArrayList<>(sourceList.size());
        for (S s : sourceList) {
            try {
                T t = tClass.getConstructor().newInstance();
                BeanUtils.copyProperties(s, t);
                targetList.add(t);
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                     NoSuchMethodException e) {
                log.info("MyBeanUtils->copyList异常->{}", e);
            }
        }
        return targetList;
    }

    /**
     * 数据转为另一个实体类
     *
     * @param s
     * @param clazz
     * @param <S>
     * @param <T>
     * @return
     */
    public static <S, T> T copy(S s, Class<T> clazz) {
        T t = null;
        try {
            t = clazz.getConstructor().newInstance();
            BeanUtils.copyProperties(s, t);
        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException |
                 IllegalAccessException e) {
            log.info("MyBeanUtils->copy异常->{}", e);
        }
        return t;
    }

    /**
     * 将Map转换为指定类型的Bean实例。
     *
     * @param map   包含属性名和值的Map
     * @param clazz 目标Bean的Class类型
     * @param <T>   Bean的类型
     * @return 转换后的Bean实例
     */
    public static <T> T mapToBean(Map<String, String> map, Class<T> clazz) {
        if (map == null || map.isEmpty() || clazz == null) {
            return null;
        }

        T t;
        boolean isNull = true;
        try {
            t = clazz.getConstructor().newInstance();
            for (Map.Entry<String, String> entry : map.entrySet()) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    String fieldName = field.getName();
                    //字段在map中不存在
                    if (!map.containsKey(fieldName)) {
                        continue;
                    }
                    String value = map.get(fieldName);
                    //值为空
                    if (Strings.isBlank(value)) {
                        continue;
                    }
                    //
                    isNull = false;
                    field.setAccessible(true);
                    Class<?> type = field.getType();
                    if (Integer.class.equals(type)) {
                        int integerValue;
                        try {
                            integerValue = Integer.parseInt(value);
                        } catch (Exception e) {
                            integerValue = 0;
                        }
                        field.set(t, integerValue);
                    } else if (LocalDateTime.class.equals(type)) {
                        LocalDateTime localDateTime;
                        try {
                            localDateTime = DateUtils.strToDateTime(value, DateTimeConstants.NORM_DATETIME_PATH_PATTERN);
                        } catch (Exception e) {
                            localDateTime = LocalDateTime.now();
                        }
                        field.set(t, localDateTime);
                    } else if (BigDecimal.class.equals(type)) {
                        BigDecimal bigDecimal;
                        try {
                            bigDecimal = new BigDecimal(value);
                        } catch (Exception e) {
                            bigDecimal = BigDecimal.ZERO;
                        }
                        field.set(t, bigDecimal);
                    } else {
                        field.set(t, value);
                    }
                }

            }
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
                 InvocationTargetException e) {
            throw new FatalBeanException("Failed to instantiate bean of class: " + clazz.getName(), e);
        }
        return isNull ? null : t;
    }

}
